package cn.yuanqiao.cqbc.fileBackup.service.impl;


import cn.hutool.core.util.StrUtil;
import cn.yuanqiao.common.exception.ServiceException;
import cn.yuanqiao.common.utils.SnowflakeIdGenerator;
import cn.yuanqiao.common.utils.SecurityUtils;
import cn.yuanqiao.cqbc.fileBackup.domain.Filebackup;
import cn.yuanqiao.cqbc.fileBackup.mapper.FilebackupMapper;
import cn.yuanqiao.cqbc.fileBackup.service.FilebackupService;
import cn.yuanqiao.cqbc.fileBackup.taskClass.FilebackupInspection;
import cn.yuanqiao.cqbc.fileBackup.util.FileUtil;
import cn.yuanqiao.cqbc.fileBackupLog.domain.FileBackupLog;
import cn.yuanqiao.cqbc.fileBackupLog.mapper.FileBackupLogMapper;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronExpression;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xy
 * @since 2023-02-28
 */
@Slf4j
@Service
public class FilebackupServiceImpl implements FilebackupService {

    @Resource
    private FileUtil fileUtil;

    @Autowired
    private FilebackupMapper filebackupMapper;
    @Autowired
    private FileBackupLogMapper filebackupLogMapper;

    @Autowired
    private ApplicationContext applicationContext;

    @Resource(name = "threadPoolTaskScheduler")
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;
    private Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();



    @Override
    public int add(Filebackup filebackup){
      filebackup.setTenantCode(SecurityUtils.getTenantCode());
       long id= SnowflakeIdGenerator.generateId();
       filebackup.setId(id);
      int i=filebackupMapper.insertFilebackup(filebackup);
        if("1".equals(filebackup.getExecutionMode())&&filebackup.getStartupStatus().equals("1")){
            FilebackupInspection filebackupInspection = applicationContext.getBean("filebackupInspection", FilebackupInspection.class);
            filebackupInspection.taskInspection(filebackup);
            ScheduledFuture scheduledFuture = threadPoolTaskScheduler.schedule(filebackupInspection, new org.springframework.scheduling.support.CronTrigger(filebackup.getExecuteExpression()));
            futureMap.put(filebackup.getId().toString(), scheduledFuture);
        }


       return i;

    }

    @Override
    public List<Filebackup> selectFilebackupList(Filebackup filebackup)
    {
        filebackup.setTenantCode(SecurityUtils.getTenantCode());
        return filebackupMapper.selectFilebackupList(filebackup);
    }

    /**
     * 修改Filebackup
     *
     * @param filebackup Filebackup
     * @return 结果
     */
    @Override
    public int updateFilebackup(Filebackup filebackup)
    {
        Filebackup oldEntity=filebackupMapper.selectFilebackupById(filebackup.getId());


        if ("1".equals(filebackup.getExecutionMode()) && filebackup.getStartupStatus().equals("1") ) {
              if (StrUtil.isNotBlank(filebackup.getExecuteExpression()) && !CronExpression.isValidExpression(filebackup.getExecuteExpression())) {
                       throw new ServiceException("执行表达式格式不正确，请输入正确的执行表达式");
             }


             ScheduledFuture scheduledFuture = null;
             FilebackupInspection filebackupInspection = applicationContext.getBean("filebackupInspection", FilebackupInspection.class);
             filebackupInspection.taskInspection(filebackup);
             if ( filebackup.getStartupStatus().equals("1") && oldEntity.getStartupStatus().equals("0")) {
                ScheduledFuture<?> future = futureMap.get(filebackup.getId().toString());
                if (future == null) {
                       log.warn("任务[{}]已不在调度中，无法停止！", filebackup.getId());
                           //return "任务[" + newEntity.getId() + "]已不在调度中，无法停止！";
                } else {
                      future.cancel(true);
                      futureMap.remove(filebackup.getId().toString());
                      log.info("任务[{}]已被停止！", filebackup.getId());
                           //return "任务[" + jobId + "]已被停止！";
                   }
                 scheduledFuture = threadPoolTaskScheduler.schedule(filebackupInspection, new org.springframework.scheduling.support.CronTrigger(filebackup.getExecuteExpression()));

                 futureMap.put(filebackup.getId().toString(), scheduledFuture);

             }
           } else if (filebackup.getStartupStatus().equals("0") && oldEntity.getStartupStatus().equals("1")) {
                   // 检测该任务是否已在运行调度中
                   ScheduledFuture<?> future = futureMap.get(filebackup.getId().toString());
                   if (future == null) {
                       log.warn("任务[{}]已不在调度中，无法停止！", filebackup.getId());
                       //return "任务[" + newEntity.getId() + "]已不在调度中，无法停止！";
                   } else {
                       future.cancel(true);
                       futureMap.remove(filebackup.getId().toString());
                       log.info("任务[{}]已被停止！", filebackup.getId());
                       //return "任务[" + jobId + "]已被停止！";
                   }

               }


        return filebackupMapper.updateFilebackup(filebackup);
    }


    /**
     * 查询Filebackup
     *
     * @param id Filebackup主键
     * @return Filebackup
     */
    @Override
    public Filebackup selectFilebackupById(Long id)
    {
        return filebackupMapper.selectFilebackupById(id);
    }

    @Override
    public int deleteFilebackupByIds(Long[] ids) {
        //停止任务
        for(int i=0;i<ids.length;i++){
            ScheduledFuture<?> future = futureMap.get(ids[i].toString());
            if (future == null) {
                log.warn("任务[{}]已不在调度中，无法停止！", ids[i].toString());
                //return "任务[" + newEntity.getId() + "]已不在调度中，无法停止！";
            } else {
                future.cancel(true);
                futureMap.remove(ids[i].toString());
                log.info("任务[{}]已被停止！", ids[i].toString());
                //return "任务[" + jobId + "]已被停止！";
            }




        }


        return filebackupMapper.deleteFilebackupByIds(ids);
    }

    @Override
    public int updateState(Filebackup filebackup) {
        Filebackup oldEntity=filebackupMapper.selectFilebackupById(filebackup.getId());


        if (filebackup.getStartupStatus().equals("1") ) {
            if (StrUtil.isNotBlank(oldEntity.getExecuteExpression()) && !CronExpression.isValidExpression(oldEntity.getExecuteExpression())) {
                throw new ServiceException("执行表达式格式不正确，请输入正确的执行表达式");
            }


            ScheduledFuture scheduledFuture = null;
            FilebackupInspection filebackupInspection = applicationContext.getBean("filebackupInspection", FilebackupInspection.class);
            filebackupInspection.taskInspection(oldEntity);

            scheduledFuture = threadPoolTaskScheduler.schedule(filebackupInspection, new org.springframework.scheduling.support.CronTrigger(oldEntity.getExecuteExpression()));

            futureMap.put(filebackup.getId().toString(), scheduledFuture);


        } else if (filebackup.getStartupStatus().equals("0") ) {
            // 检测该任务是否已在运行调度中
            ScheduledFuture<?> future = futureMap.get(filebackup.getId().toString());
            if (future == null) {
                log.warn("任务[{}]已不在调度中，无法停止！", filebackup.getId());
                //return "任务[" + newEntity.getId() + "]已不在调度中，无法停止！";
            } else {
                future.cancel(true);
                futureMap.remove(filebackup.getId().toString());
                log.info("任务[{}]已被停止！", filebackup.getId());
                //return "任务[" + jobId + "]已被停止！";
            }

        }


        return filebackupMapper.updateFilebackup(filebackup);
    }


//    @Override
//    public void update(FilebackupParam param){
//        Filebackup oldEntity = getOldEntity(param);
//        Filebackup newEntity = getEntity(param);
//        ToolUtil.copyProperties(newEntity, oldEntity);
//           if(param.getIsDel()!=null&&"1".equals(param.getIsDel())){
//               if ("1".equals(oldEntity.getExecutionMode()) && oldEntity.getStartupStatus().equals("1")){
//                   ScheduledFuture<?> future = futureMap.get(param.getId().toString());
//                   if (future == null) {
//                       log.warn("任务[{}]已不在调度中，无法停止！", newEntity.getId());
//                       //return "任务[" + newEntity.getId() + "]已不在调度中，无法停止！";
//                   } else {
//                       future.cancel(true);
//                       futureMap.remove(newEntity.getId().toString());
//                       log.info("任务[{}]已被停止！", newEntity.getId());
//                       //return "任务[" + jobId + "]已被停止！";
//                   }
//
//               }
//           }else {
//               if ("1".equals(oldEntity.getExecutionMode()) && param.getStartupStatus().equals("1") && !oldEntity.getIsDel().equals("1")) {
//                   if (StrUtil.isNotBlank(oldEntity.getExecuteExpression()) && !CronExpression.isValidExpression(oldEntity.getExecuteExpression())) {
//                       throw new ServiceException(500, "执行表达式格式不正确，请输入正确的执行表达式");
//                   }
//
//                   param.setExecuteExpression(oldEntity.getExecuteExpression());
//                   param.setAssignmentName(oldEntity.getAssignmentName());
//                   param.setAssignmentNumber(oldEntity.getAssignmentNumber());
//                   param.setBackupAddress(oldEntity.getBackupAddress());
//                   param.setBackupMethod(oldEntity.getBackupMethod());
//                   param.setOriginalAddress(oldEntity.getOriginalAddress());
//                   param.setStartupStatus(oldEntity.getStartupStatus());
//                   param.setCreateUser(oldEntity.getCreateUser());
//
//                   ScheduledFuture scheduledFuture = null;
//                   FilebackupInspection filebackupInspection = applicationContext.getBean("filebackupInspection", FilebackupInspection.class);
//                   filebackupInspection.taskInspection(param);
//
//
//                   if ("1".equals(oldEntity.getExecutionMode()) && param.getStartupStatus().toString().equals("1") && !oldEntity.getIsDel().equals("1")) {
//
//
//                       ScheduledFuture<?> future = futureMap.get(param.getId().toString());
//                       if (future == null) {
//                           log.warn("任务[{}]已不在调度中，无法停止！", newEntity.getId());
//                           //return "任务[" + newEntity.getId() + "]已不在调度中，无法停止！";
//                       } else {
//                           future.cancel(true);
//                           futureMap.remove(newEntity.getId().toString());
//                           log.info("任务[{}]已被停止！", newEntity.getId());
//                           //return "任务[" + jobId + "]已被停止！";
//                       }
//                       scheduledFuture = threadPoolTaskScheduler.schedule(filebackupInspection, new org.springframework.scheduling.support.CronTrigger(oldEntity.getExecuteExpression()));
//
//                       futureMap.put(param.getId().toString(), scheduledFuture);
//
//                   }
//               } else if ("1".equals(oldEntity.getExecutionMode()) && param.getStartupStatus().equals("0") && !oldEntity.getIsDel().equals("1")) {
//                   // 检测该任务是否已在运行调度中
//                   ScheduledFuture<?> future = futureMap.get(param.getId().toString());
//                   if (future == null) {
//                       log.warn("任务[{}]已不在调度中，无法停止！", newEntity.getId());
//                       //return "任务[" + newEntity.getId() + "]已不在调度中，无法停止！";
//                   } else {
//                       future.cancel(true);
//                       futureMap.remove(newEntity.getId().toString());
//                       log.info("任务[{}]已被停止！", newEntity.getId());
//                       //return "任务[" + jobId + "]已被停止！";
//                   }
//
//               }
//           }
//
//
//
//
//        this.updateById(newEntity);
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void backup(Filebackup filebackup) {
        //进行备份
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String beginTime=sdf.format(new Date());
        FileBackupLog filebackupLog=filebackupLogMapper.getFilebackupLogByFilebackupId(filebackup.getId());
        filebackup=filebackupMapper.selectFilebackupById(filebackup.getId());
        String backupMethod=filebackup.getBackupMethod();

        try {
            if ("1".equals(backupMethod)) {
                //开始备份
                fileUtil.copy(new File(filebackup.getOriginalAddress()), new File(filebackup.getBackupAddress()),filebackup.getOriginalAddress());
            }else if("0".equals(backupMethod)){
                fileUtil.incrementCopy(new File(filebackup.getOriginalAddress()), new File(filebackup.getBackupAddress()),filebackup.getOriginalAddress());

            }
        }catch (Exception ex){
            ex.printStackTrace();
        }

        String endTime=sdf.format(new Date());
        if(filebackupLog==null){
            filebackupLog=new FileBackupLog();
            filebackupLog.setId(SnowflakeIdGenerator.generateId());
            filebackupLog.setFilebackupId(filebackup.getId());
            filebackupLog.setBeginTime(beginTime);
            filebackupLog.setEndTime(endTime);
            filebackupLog.setCreateTime(sdf.format(new Date()));
            filebackupLog.setTenantCode(filebackup.getTenantCode());
            filebackupLogMapper.insertFileBackupLog(filebackupLog);
        }else{
            filebackupLog.setBeginTime(beginTime);
            filebackupLog.setEndTime(endTime);
            filebackupLogMapper.updateFileBackupLog(filebackupLog);
        }


    }


}
